package com.astoolkit.workflow.task.io
{
	import com.astoolkit.workflow.BaseTask;
	import com.astoolkit.workflow.BaseTask;
	
	import deng.fzip.FZip;
	import deng.fzip.FZipErrorEvent;
	import deng.fzip.FZipEvent;
	import deng.fzip.FZipFile;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	public class UnzipFileFromUrlTask extends BaseTask
	{
		public var destinationUrl : String;
		public var sourceUrl : String;
		
		private var destinationFile : File;
		
		override public function prepare() : void
		{
			super.prepare();
			destinationFile = null;
			if( sourceUrl == null )
				sourceUrl = _pipelineData;
			if( sourceUrl == null )
				fail( "Invalid source URL" );
		}
		
		override public function begin() : void
		{
			super.begin();
			destinationFile = new File();
			destinationFile.url = destinationUrl;

			
			if( destinationFile.isDirectory )
				destinationFile.deleteDirectory( true );
			var zip : FZip = new FZip();
			zip.addEventListener( IOErrorEvent.IO_ERROR, onError );
			zip.addEventListener( FZipErrorEvent.PARSE_ERROR, onError );
			zip.addEventListener( SecurityErrorEvent.SECURITY_ERROR, onError );
			zip.addEventListener( FZipEvent.FILE_LOADED, onZFileLoaded );
			zip.addEventListener( Event.COMPLETE, onDownloadComplete );
			zip.addEventListener( ProgressEvent.PROGRESS, onDownloadProgress );
			zip.load( new URLRequest( sourceUrl ) );
			setProgress( 0 );
		}
		
		private function onError( inEvent : Event ) : void
		{
			fail( "Error downloading or unzipping file" );
		}
		
		private function onDownloadProgress( inEvent : ProgressEvent ) : void
		{
			setProgress( inEvent.bytesLoaded / inEvent.bytesTotal );
		}
		
		private function onZFileLoaded( inEvent : FZipEvent ) : void
		{
			try{
				var tFile:FZipFile = inEvent.file;
				
				var stream:FileStream = new FileStream();
				
				createRequiredDirectories(tFile.filename);
				
				var fileToWrite:File = destinationFile.resolvePath(tFile.filename);
				
				if(fileToWrite.isDirectory){
					return;
				}
				// open and write to the file stream
				stream.open( fileToWrite, FileMode.WRITE );
				var contentByteArray:ByteArray = tFile.content;
				stream.writeBytes(contentByteArray);
				stream.close();
			} catch (error:Error) {
				cleanCache();
				fail( error.message );
			}
		}
		
		private function createRequiredDirectories(fileDirectory:String):void{
			var directoryArray:Array = fileDirectory.split("/");
			var workingDirectory:File = destinationFile;
			var iLength:uint = directoryArray.length-1;
			for(var i:uint = 0;i<iLength;i++){
				var directoryName:String = directoryArray[i];
				var nextWorkingDirectory:File = workingDirectory.resolvePath(directoryName);
				if(nextWorkingDirectory.exists){
					if( !nextWorkingDirectory.isDirectory )
					{
						throw new Error( nextWorkingDirectory.nativePath + " is not a directory" )
					}
				} else {
					var newDir : File = File.createTempDirectory();
					var nextWorkingDirectoryProxy:File = newDir.resolvePath( directoryName );
					nextWorkingDirectoryProxy.createDirectory();
					nextWorkingDirectoryProxy.copyTo(nextWorkingDirectory);
				}
				workingDirectory = nextWorkingDirectory;
			}
		}
		
		private function cleanCache() : void
		{
			var file : File = destinationFile;
			if( file.exists && file.isDirectory )
				file.deleteDirectory( true );
		}
		
		
		private function onDownloadComplete( inEvent : Event ) : void
		{
			_pipelineData = destinationFile;
			complete();
		}
	}
}